# -*- coding: utf-8 -*-
"""
Created on Fri May 26 08:24:44 2017

@author: fuli
"""

import ctypes
import os
import platform

TESSDATA_PREFIX = 'tessdata'
LIBNAME = 'libtesseract304'

class TesseractError(Exception):
    pass


class Tesseract:
    _lib = None
    _api = None

    class TessBaseAPI(ctypes._Pointer):
        _type_ = type('_TessBaseAPI', (ctypes.Structure,), {})

    def __init__(self, language='eng', datapath=None, lib_path=None):
        os.environ['PATH'] = os.path.dirname(__file__) + ';' + os.environ['PATH']
        libpath = self._check_ver()
        os.environ['PATH'] = os.path.dirname(__file__) + "/" + libpath + ';' + os.environ['PATH']
        
        if self._lib is None:
            self.loadLib(lib_path)

        self._api = self._lib.TessBaseAPICreate()

        if datapath is None:
            datapath = os.path.dirname(__file__) + os.path.sep + TESSDATA_PREFIX

        if self._lib.TessBaseAPIInit3(self._api, datapath, language):
            raise TesseractError('initialization failed')

    def __del__(self):
        if not self._lib or not self._api:
            return
        if not getattr(self, 'closed', False):
            self._lib.TessBaseAPIDelete(self._api)
            self.closed = True
    
    @classmethod
    def loadLib(cls, lib_path=None):
        if cls._lib is not None:
            return
        
        if lib_path is None:
            lib_path = ctypes.util.find_library(LIBNAME)
            if lib_path is None:
                 raise TesseractError('tesseract library not found')

        cls._lib = lib = ctypes.CDLL(lib_path)
            
        lib.TessBaseAPICreate.restype = cls.TessBaseAPI

        lib.TessBaseAPIDelete.restype = None # void
        lib.TessBaseAPIDelete.argtypes = (cls.TessBaseAPI,) # handle

        lib.TessBaseAPIInit3.argtypes = (
            cls.TessBaseAPI, # handle
            ctypes.c_char_p, # datapath
            ctypes.c_char_p) # language

        lib.TessBaseAPISetImage.restype = None
        lib.TessBaseAPISetImage.argtypes = (
            cls.TessBaseAPI, # handle
            ctypes.c_void_p, # imagedata
            ctypes.c_int,    # width
            ctypes.c_int,    # height
            ctypes.c_int,    # bytes_per_pixel
            ctypes.c_int)    # bytes_per_line

        lib.TessBaseAPIGetUTF8Text.restype = ctypes.c_char_p
        lib.TessBaseAPIGetUTF8Text.argtypes = (cls.TessBaseAPI,) # handle

    def _check_loaded(self):
        if not self._lib:
            raise TesseractError('lib not configured')
        if not self._api:
            raise TesseractError('api not created')

    def _check_ver(self):    
        ver = platform.architecture()[0]
        if ver == "64bit":
            return "x64"
        elif ver == "32bit":
            return "x86"
        else:
            return "lib"
    
    def ocr(self, path):
        self._check_loaded()
        self._lib.TessBaseAPIProcessPages(self._api, path, None, 0, None)
        text_out = self._lib.TessBaseAPIGetUTF8Text(self._api)
        result = ctypes.string_at(text_out)
        return result.strip()

    def demo(self):
        return self.ocr(b'./test.jpg')
        
        
if __name__ == '__main__':
    tess = Tesseract()
    result = tess.demo()
    print(result)